﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml.Linq;
using System.Xml.XPath;
using umbraco;

namespace uHelpsy.Core
{
    public static class LinqExtensions
    {


        #region Element methods

        #region HasElementWhereNameIs
        /// <summary>
        /// Gets the value of the current XElement where name == name
        /// </summary>
        /// <param name="x">The current XElement</param>
        /// <param name="name">The name of the value</param>
        /// <returns>The value of the current XElement where name == name</returns>
        public static bool HasElementWhereNameIs(this XElement x, string name)
        {
            return x.Elements()
                    .Where(y => y.Name == name)
                    .Count() > 0;
        }
        
        #endregion


        #region GetValueWhereElementNameIs
        /// <summary>
        /// Gets the value from the current XElement's Element list where the element name == name
        /// </summary>
        /// <param name="x">The current XElement</param>
        /// <param name="name">The name of the value</param>
        /// <returns>The value of the current XElement where name == name</returns>
        public static string GetValueWhereElementNameIs(this XElement x, string name)
        {
            return x.Elements()
                    .Where(y => y.Name == name)
                    .Select(y => y.Value)
                    .SingleOrDefault();
        }
        
        #endregion


        #region GetDescendantsWhereElementExists
        /// <summary>
        /// Gets descendents which have element == elementName.
        /// </summary>
        /// <param name="x">The current XElement</param>
        /// <param name="elementName">The name of the element to look for</param>
        /// <returns>Descendents which have element == elementName.</returns>
        public static IEnumerable<XElement> GetDescendantsWhereElementExists(this XElement x, string elementName)
        {
            return x.Descendants()
                    .Where(y => y.HasElementWhereNameIs(elementName));
        }
        #endregion


        #endregion




        #region Descendent methods


        #region HasDescendantsWhereNameIs

        /// <summary>
        /// Returns true if current XElement has descendants with name == name. 
        /// </summary>
        /// <param name="x">The current XElement</param>
        /// <param name="name">The name of the node to search for</param>
        /// <returns>True if current XElement has descendants with name == name, else returns false. </returns>
        public static bool HasDescendantsWhereNameIs(this XElement x, string name)
        {
            return x.GetDescendantsWhereNameIs(name)
                    .Count() > 0;
        }

        #endregion


        #region GetDescendentsWhereNameIs

        /// <summary>
        /// Gets descendants of the current XElement where node name == name.
        /// </summary>
        /// <param name="x">The current XElement</param>
        /// <param name="name">The name of the xml node to search for</param>
        /// <returns>Descendants of the current XElement where node name == name.</returns>
        public static IEnumerable<XElement> GetDescendantsWhereNameIs(this XElement x, string name)
        {
            return x.Descendants()
                    .Where(y => y.Name == name);
        }


        #endregion


        
        #endregion




        #region Attribute methods


        #region HasAttribute
        /// <summary>
        /// Returns true when the attribute exists, else returns false.
        /// </summary>
        /// <param name="x">The current XElement</param>
        /// <param name="name">The name of the attribute</param>
        /// <returns>True when the attribute exists, else returns false.</returns>
        public static bool HasAttribute(this XElement x, string name)
        {
            return x.Attribute(name) == null ? false : true;
        }

        #endregion


        #region GetAttributeOrDefault
        /// <summary>
        /// Gets the attribute value, or null if it does not exist
        /// </summary>
        /// <param name="x">The current XElement</param>
        /// <param name="name">The name of the attribute</param>
        /// <returns>The attribute value, or null if it does not exist</returns>
        public static string GetAttributeOrDefault(this XElement x, string name)
        {
            if (x.HasAttribute(name))
                return x.Attribute(name).Value;
            return null;
        }

        #endregion


        #region GetDescendantsWhereAttributeExists

        /// <summary>
        /// Gets the descendants which have the attribute.
        /// </summary>
        /// <param name="x">The current XElement</param>
        /// <param name="attribute">The attribute name to check</param>
        /// <returns>The descendants which have the attribute.</returns>
        public static IEnumerable<XElement> GetDescendantsWhereAttributeExists(this XElement x, string attribute)
        {
            return x.Descendants()
                    .Where(y => y.HasAttribute(attribute));
        }
        
        #endregion

        
        #region GetDescendantsWhereAttributeIs

        /// <summary>
        /// Gets descendants which have the attribute value == value.
        /// </summary>
        /// <param name="x">The current XElement</param>
        /// <param name="propertyName"></param>
        /// <param name="value"></param>
        /// <returns></returns>
        public static IEnumerable<XElement> GetDescendantsWhereAttributeIs(this XElement x, string attribute, string value)
        {
            return x.Descendants()
                       .Where(y => y.HasAttribute(attribute))
                       .Where(y => y.GetAttributeOrDefault(attribute) == value);
        }

        #endregion

                
        #endregion





    }
}
